#include "sysconfig.h"
#include "options.h"
#include "dxwrap.h"
#include "win32gfx.h"
#include "gfxfilter.h"
#include "direct3d.h"
#include "drawing.h"
#include "win32.h"
#include "statusline.h"

struct uae_filter uaefilters[] =
{
    { UAE_FILTER_NULL, 1, L"Null filter", L"null", UAE_FILTER_MODE_16_16 | UAE_FILTER_MODE_32_32 },

    { UAE_FILTER_SCALE2X, 2, L"Scale2X", L"scale2x", UAE_FILTER_MODE_16_16 | UAE_FILTER_MODE_32_32 },

    { UAE_FILTER_SUPEREAGLE, 2, L"SuperEagle", L"supereagle", UAE_FILTER_MODE_16_16 | UAE_FILTER_MODE_16_32 },

    { UAE_FILTER_SUPER2XSAI, 2, L"Super2xSaI", L"super2xsai", UAE_FILTER_MODE_16_16 | UAE_FILTER_MODE_16_32 },

    // { UAE_FILTER_HQ4X, 0, 4, L"hq4x", L"hq4x", UAE_FILTER_MODE_16_16 | UAE_FILTER_MODE_16_32 },

    // { UAE_FILTER_SUPEREAGLE, 0, 2, L"SuperEagle", L"supereagle", UAE_FILTER_MODE_16_16 | UAE_FILTER_MODE_16_32 },

    // { UAE_FILTER_SUPER2XSAI, 0, 2, L"Super2xSaI", L"super2xsai", UAE_FILTER_MODE_16_16 | UAE_FILTER_MODE_16_32 },

    { UAE_FILTER_2XSAI, 2, L"2xSaI", L"2xsai", UAE_FILTER_MODE_16_16 | UAE_FILTER_MODE_16_32 },

    // { UAE_FILTER_PAL, 1, 1, L"PAL", L"pal", UAE_FILTER_MODE_16_16 | UAE_FILTER_MODE_32_32 },

    { 0 }
};

static int filteroffsetx, filteroffsety, filterxmult = 1000, filterymult = 1000;
static int dst_width, dst_height, amiga_width, amiga_height, amiga_depth, dst_depth, scale;
static int dst_width2, dst_height2, amiga_width2, amiga_height2, amiga_depth2, dst_depth2;
static int temp_width, temp_height;
byte* bufmem_ptr;
// static LPDIRECTDRAWSURFACE7 tempsurf;
// static byte* tempsurf2, * tempsurf3;
// static int cleartemp;
static uint rc[256], gc[256], bc[256];
static int deskw, deskh;
// static int d3d;
static bool inited;

void getfilteroffset(int* dx, int* dy, int* mx, int* my)
{
    *dx = filteroffsetx;
    *dy = filteroffsety;
    *mx = filterxmult;
    *my = filterymult;
}

static void getinit()
{
    if (isfullscreen())
    {
        struct MultiDisplay* md = getdisplay(&g_curr_conf);

        deskw = md->rect.right - md->rect.left;
        deskh = md->rect.bottom - md->rect.top;
    }
    else
    {
        deskw = dst_width;
        deskh = dst_height;
    }
}

static int vblscale(int v)
{
    static int o;
    int n, v2;

    n = (beamcon0 & 0x80) + maxvpos_nom;
    // if (n != o)
    //     cleartemp = 1;
    o = n;
    if (beamcon0 & 0x80)
        return v;
    if (g_curr_conf.ntscmode)
        v2 = MAXVPOS_NTSC;
    else
        v2 = MAXVPOS_PAL;
    if (abs(v2 - maxvpos_nom) <= 3)
        return v;
    v = v * maxvpos_nom / v2;
    return v;
}
static int vblscale2(int v)
{
    static int o;
    int n;

    n = (beamcon0 & 0x80) + maxvpos_nom;
    // if (n != o)
    //     cleartemp = 1;
    o = n;
    if (beamcon0 & 0x80)
        return v;
    v = v * maxvpos_nom / MAXVPOS_PAL;
    return v;
}

static void fixh(int* ah, int* th, int minh)
{
    if (!(beamcon0 & 0x80))
    {
        int max = (AMIGA_HEIGHT_MAX * scale) << g_curr_conf.gfx_vresolution;
        if (minh && max < minh)
            max = minh;
        if (*ah > max)
            *ah = max;
        if (*th > max)
            *th = max;
    }
}

// static byte * getfilterrect1(RECT* sr, RECT* dr, int dst_width, int dst_height, int dst_depth, int aw, int ah, int scale, int temp_width, int temp_height, byte* dptr, int pitch)
// {
//     int aws, ahs;
//
//     fixh(&ah, &temp_height, dst_height);
//
//     aws = aw * scale;
//     ahs = ah * scale;
//
//     SetRect(sr, 0, 0, 0, 0);
//     dr->left = sr->left + (temp_width - aws) / 2;
//     dr->top = sr->top + (temp_height - ahs) / 2;
//     dptr += dr->left * (dst_depth / 8);
//     dptr += dr->top * pitch;
//     return dptr;
// }

static void sizeoffset(RECT* dr, RECT* zr, int w, int h)
{
    dr->right -= w;
    dr->bottom -= h;
    OffsetRect(zr, w / 2, h / 2);
}

void getfilterrect2(RECT* sr, RECT* dr, RECT* zr, int dst_width, int dst_height, int aw, int ah, int scale, int temp_width, int temp_height)
{
    float srcratio, dstratio;
    int aws, ahs, ahs2;
    int xs, ys;
    // int v;
    // int extraw, extrah;
    int fpuv;

    // int filter_horiz_zoom = g_curr_conf.gfx_filter_horiz_zoom;
    // int filter_vert_zoom = g_curr_conf.gfx_filter_vert_zoom;
    // int filter_horiz_zoom_mult = g_curr_conf.gfx_filter_horiz_zoom_mult;
    // int filter_vert_zoom_mult = g_curr_conf.gfx_filter_vert_zoom_mult;
    // int filter_horiz_offset = g_curr_conf.gfx_filter_horiz_offset;
    // int filter_vert_offset = g_curr_conf.gfx_filter_vert_offset;

    // if (!usedfilter && !g_curr_conf.gfx_api)
    // {
    //     filter_horiz_zoom = filter_vert_zoom = 0;
    //     filter_horiz_zoom_mult = filter_vert_zoom_mult = 1000;
    //     filter_horiz_offset = filter_vert_offset = 0;
    // }

    if (screen_is_picasso)
    {
        getrtgfilterrect2(sr, dr, zr, dst_width, dst_height);
        return;
    }

    fpux_save(&fpuv);

    fixh(&ah, &temp_height, dst_height);

    getinit();
    ahs2 = vblscale(ah) * scale;
    aws = aw * scale;
    ahs = ah * scale;
    // Logger::Write(L"%d %d %d\n", dst_width, temp_width, aws);
    // extraw = -aws * (filter_horiz_zoom - g_curr_conf.gfx_filteroverlay_overscan * 10) / 2000;
    // extrah = -ahs * (filter_vert_zoom - g_curr_conf.gfx_filteroverlay_overscan * 10) / 2000;

    SetRect(sr, 0, 0, dst_width, dst_height);
    SetRect(zr, 0, 0, 0, 0);
    dr->left = (temp_width - aws) / 2;
    dr->top = (temp_height - ahs) / 2;

    filteroffsetx = 0;
    filteroffsety = 0;
    float xmult = g_curr_conf.gfx_filter_zoom_mult;
    float ymult = g_curr_conf.gfx_filter_zoom_mult;

    dr->left -= (dst_width - aws) / 2;
    dr->top -= (dst_height - ahs) / 2;
    dr->right = dr->left + dst_width;
    dr->bottom = dr->top + dst_height;

    srcratio = 4.0 / 3.0;
    if (g_curr_conf.gfx_filter_aspect > 0)
    {
        dstratio = (g_curr_conf.gfx_filter_aspect >> 8) * 1.0 / (g_curr_conf.gfx_filter_aspect & 0xff);
    }
    else if (g_curr_conf.gfx_filter_aspect < 0)
    {
        if (isfullscreen() && deskw > 0 && deskh > 0)
            dstratio = 1.0 * deskw / deskh;
        else
            dstratio = 1.0 * dst_width / dst_height;
    }
    else
    {
        dstratio = srcratio;
    }

    int scalemode = g_curr_conf.gfx_filter_autoscale;

    // if (scalemode == AUTOSCALE_STATIC_AUTO)
    // {
    //     if (g_curr_conf.gfx_afullscreen)
    //     {
    //         scalemode = AUTOSCALE_STATIC_NOMINAL;
    //     }
    //     else
    //     {
    //         int w1 = (800 / 2) << g_curr_conf.gfx_resolution;
    //         int w2 = (640 / 2) << g_curr_conf.gfx_resolution;
    //         int h1 = (600 / 2) << g_curr_conf.gfx_vresolution;
    //         int h2 = (400 / 2) << g_curr_conf.gfx_vresolution;
    //         int w = g_curr_conf.gfx_size_win.width;
    //         int h = g_curr_conf.gfx_size_win.height;
    //         if (w <= w1 && h <= h1 && w >= w2 && h >= h2)
    //             scalemode = AUTOSCALE_NONE;
    //         else
    //             scalemode = AUTOSCALE_STATIC_NOMINAL;
    //     }
    // }

    if (scalemode)
    {
        int cw, ch, cx, cy, cv;
        static int oxmult, oymult;

        filterxmult = 1000 / scale;
        filterymult = 1000 / scale;

        // if (scalemode == AUTOSCALE_STATIC_MAX || scalemode == AUTOSCALE_STATIC_NOMINAL)
        // {
        //     cw = AMIGA_WIDTH_MAX << g_curr_conf.gfx_resolution;
        //     ch = AMIGA_HEIGHT_MAX << g_curr_conf.gfx_vresolution;
        //     cx = 0;
        //     cy = 0;
        //     cv = 1;
        //     if (scalemode == AUTOSCALE_STATIC_NOMINAL)
        //     {
        //         cw -= 40 << g_curr_conf.gfx_resolution;
        //         ch -= 25 << g_curr_conf.gfx_vresolution;
        //         cx = 28 << g_curr_conf.gfx_resolution;
        //         cy = 10 << g_curr_conf.gfx_vresolution;
        //     }
        // }
        // else if (scalemode == AUTOSCALE_MANUAL)
        // {
        //     int v;
        //
        //     g_changed_conf.gfx_filter_horiz_offset = g_curr_conf.gfx_filter_horiz_offset = 0;
        //     g_changed_conf.gfx_filter_vert_offset = g_curr_conf.gfx_filter_vert_offset = 0;
        //     filter_horiz_offset = 0;
        //     filter_vert_offset = 0;
        //
        //     get_custom_topedge(&cx, &cy);
        //     //Logger::Write(L"%dx%d %dx%d\n", cx, cy, g_curr_conf.gfx_resolution, g_curr_conf.gfx_vresolution);
        //
        //     v = g_curr_conf.gfx_xcenter_pos;
        //     if (v >= 0)
        //         cx = (v >> (RES_MAX - g_curr_conf.gfx_resolution)) - cx;
        //
        //     v = g_curr_conf.gfx_ycenter_pos;
        //     if (v >= 0)
        //         cy = (v >> (VRES_MAX - g_curr_conf.gfx_vresolution)) - cy;
        //
        //     v = g_curr_conf.gfx_xcenter_size;
        //     if (v <= 0)
        //         cw = AMIGA_WIDTH_MAX * 4;
        //     else
        //         cw = v;
        //     cw >>= (RES_MAX - g_curr_conf.gfx_resolution);
        //
        //     v = g_curr_conf.gfx_ycenter_size;
        //     if (v <= 0)
        //         ch = AMIGA_HEIGHT_MAX * 2;
        //     else
        //         ch = v;
        //     ch >>= (VRES_MAX - g_curr_conf.gfx_vresolution);
        //
        //     //Logger::Write(L"%dx%d %dx%d %dx%d\n", g_curr_conf.gfx_xcenter_pos, g_curr_conf.gfx_ycenter_pos, cx, cy, cw, ch);
        //
        //     cv = 1;
        //
        // }
        // else
        // {
        cv = get_custom_limits(&cw, &ch, &cx, &cy);
        // }

        // if (g_curr_conf.gfx_api == 0)
        // {
        //     if (cx < 0)
        //         cx = 0;
        //     if (cy < 0)
        //         cy = 0;
        // }

        if (cv)
        {
            int diff;

            // if (scalemode == AUTOSCALE_CENTER)
            // {
            //
            //     int ww = cw * scale;
            //     int hh = ch * scale;
            //     SetRect(sr, 0, 0, dst_width, dst_height);
            //     SetRect(zr, 0, 0, 0, 0);
            //     dr->left = dr->top = 0;
            //     dr->right = dr->left + dst_width;
            //     dr->bottom = dr->top + dst_height;
            //     OffsetRect(zr, cx * scale - (dst_width - ww) / 2, cy * scale - (dst_height - hh) / 2);
            //     goto cont;
            //
            // }
            // else
            if (g_curr_conf.gfx_filter_autoscale == AUTOSCALE_RESIZE && isfullscreen() == 0)
            {
                static int lastresize = 0;
                static int lastdelay = 1;
                static int ocw, och, ocx, ocy, lcw, lch, lcx, lcy;
                int useold = 0;

                lastresize--;
                if (lastresize > 0)
                {
                    if (cw != lcw || ch != lch || cx != lcx || cy != lcy)
                        lastresize = 10;
                    useold = 1;
                }
                else if (lastdelay == 0)
                {
                    lastdelay = 2;
                    useold = 1;
                }
                else if (lastdelay > 0)
                {
                    lastdelay--;
                    useold = 1;
                    if (lastdelay == 0)
                    {
                        lastdelay = -1;
                        useold = 0;
                    }
                }

                lcw = cw;
                lch = ch;
                lcx = cx;
                lcy = cy;
                if (useold && !config_changed)
                {
                    cw = ocw;
                    ch = och;
                    cx = ocx;
                    cy = ocy;
                }
                else
                {
                    ocw = cw;
                    och = ch;
                    ocx = cx;
                    ocy = cy;
                    lastresize = 10;
                    lastdelay = 0;
                }

                // double scalex = g_curr_conf.gfx_filter_horiz_zoom_mult ? 1000.0 / g_curr_conf.gfx_filter_horiz_zoom_mult : 1.0;
                // double scaley = g_curr_conf.gfx_filter_zoom_mult ? 1000.0 / g_curr_conf.gfx_filter_zoom_mult : 1.0;
                SetRect(sr, 0, 0, cw * scale * scale, ch * scale * scale);
                dr->left = (temp_width - aws) / 2;
                dr->top = (temp_height - ahs) / 2;
                dr->right = dr->left + cw * scale;
                dr->bottom = dr->top + ch * scale;
                OffsetRect(zr, cx * scale, cy * scale);
                int ww = (dr->right - dr->left) * scale;
                int hh = (dr->bottom - dr->top) * scale;
                // if (g_curr_conf.gfx_xcenter_size >= 0)
                //     ww = g_curr_conf.gfx_xcenter_size;
                // if (g_curr_conf.gfx_ycenter_size >= 0)
                //     hh = g_curr_conf.gfx_ycenter_size;
                int oldwinw = g_curr_conf.gfx_size_win.width;
                int oldwinh = g_curr_conf.gfx_size_win.width;
                g_changed_conf.gfx_size_win.width = ww;
                g_changed_conf.gfx_size_win.height = hh;
                fixup_prefs_dimensions(&g_changed_conf);
                if (oldwinw != g_changed_conf.gfx_size_win.width || oldwinh != g_changed_conf.gfx_size_win.height)
                    config_changed = 1;
                OffsetRect(zr, -(g_changed_conf.gfx_size_win.width - ww + 1) / 2, -(g_changed_conf.gfx_size_win.height - hh + 1) / 2);
                filteroffsetx = -zr->left / scale;
                filteroffsety = -zr->top / scale;
                goto end;
            }

            dr->left = (temp_width - aws) / 2;
            dr->top = (temp_height - ahs) / 2;
            dr->right = dr->left + dst_width * scale;
            dr->bottom = dr->top + dst_height * scale;

            OffsetRect(zr, cx * scale, cy * scale);

            // sizeoffset(dr, zr, extraw, extrah);

            dr->right -= (dst_width - cw) * scale;
            dr->bottom -= (dst_height - ch) * scale;

            filteroffsetx = -zr->left / scale;
            filteroffsety = -zr->top / scale;

            if (g_curr_conf.gfx_filter_keep_aspect || g_curr_conf.gfx_filter_aspect != 0)
            {
                int diffx = dr->right - dr->left;
                int diffy = dr->bottom - dr->top;
                float xmult = 1.0;
                float ymult = 1.0;

                if (g_curr_conf.gfx_filter_keep_aspect)
                {
                    dstratio = dstratio * (aws * 1.0 / ahs2) / (cw * 1.0 / ch);
                    if (g_curr_conf.ntscmode)
                    {
                        dstratio = dstratio * 1.21;
                        if (g_curr_conf.gfx_filter_keep_aspect == 2 && ispal())
                            dstratio = dstratio * 0.93;
                        else if (g_curr_conf.gfx_filter_keep_aspect == 1 && !ispal())
                            dstratio = dstratio * 0.98;
                    }
                    else
                    {
                        if (g_curr_conf.gfx_filter_keep_aspect == 2 && ispal())
                            dstratio = dstratio * 0.95;
                        else if (g_curr_conf.gfx_filter_keep_aspect == 1 && !ispal())
                            dstratio = dstratio * 0.95;
                    }
                }

                if (srcratio > dstratio)
                {
                    ymult = ymult * srcratio / dstratio;
                }
                else
                {
                    xmult = xmult * dstratio / srcratio;
                }

                diff = diffx - diffx * xmult;
                sizeoffset(dr, zr, diff, 0);
                filteroffsetx += diff / 2;

                diff = diffy - diffy * ymult;
                sizeoffset(dr, zr, 0, diff);
                filteroffsety += diff / 2;
            }

            // v = filter_horiz_offset;
            // OffsetRect(zr, (int)(-v * aws / 1000.0), 0);
            // v = filter_vert_offset;
            // OffsetRect(zr, 0, (int)(-v * ahs / 1000.0));

            diff = dr->right - dr->left;
            filterxmult = diff * 1000 / (dst_width * scale);
            diff = dr->bottom - dr->top;
            filterymult = diff * 1000 / (dst_height * scale);
            goto end;
        }
    }

    // cont:

    if (!g_curr_conf.gfx_filter_zoom_mult)
    {
        // sizeoffset(dr, zr, extraw, extrah);

        if (g_curr_conf.gfx_filter_keep_aspect)
        {
            float xm, ym, m;

            xm = 1.0 * aws / dst_width;
            ym = 1.0 * ahs / dst_height;
            if (xm < ym)
                xm = ym;
            else
                ym = xm;
            xmult = ymult = xm * 1000.0;

            m = (aws * 1.0 / dst_width) / (ahs * 1.0 / dst_height);
            dstratio = dstratio * m;
        }
    }

    if (g_curr_conf.ntscmode)
    {
        if (g_curr_conf.gfx_filter_keep_aspect == 2 && ispal()) // TV
            dstratio = dstratio * 0.93;
        else if (g_curr_conf.gfx_filter_keep_aspect == 1 && !ispal()) // VGA
            dstratio = dstratio * 0.98;
    }
    else
    {
        if (g_curr_conf.gfx_filter_keep_aspect == 2 && ispal()) // TV
            dstratio = dstratio * 0.95;
        else if (g_curr_conf.gfx_filter_keep_aspect == 1 && !ispal()) // VGA
            dstratio = dstratio * 0.95;
    }

    if (srcratio > dstratio)
    {
        ymult = ymult * srcratio / dstratio;
    }
    else
    {
        xmult = xmult * dstratio / srcratio;
    }

    if (xmult <= 0.01)
        xmult = aws * 1000 / dst_width;
    // else
    //     xmult = xmult + xmult * filter_horiz_zoom / 2000;
    if (ymult <= 0.01)
        ymult = ahs * 1000 / dst_height;
    // else
    //     ymult = ymult + ymult * filter_vert_zoom / 2000;

    if (!g_curr_conf.gfx_filter_zoom_mult)
    {
        if (g_curr_conf.ntscmode)
        {
            int v = vblscale2(ahs);
            ymult /= 1.21f;
            OffsetRect(dr, 0, (v - ahs2) / 2);
        }
    }

    ymult = vblscale(ymult);
    OffsetRect(dr, 0, (ahs2 - ahs) / 2);

    // v = filter_horiz_offset;
    // OffsetRect(zr, (int)(-v * aws / 1000.0), 0);
    // v = filter_vert_offset;
    // OffsetRect(zr, 0, (int)(-v * ahs / 1000.0));

    xs = dst_width - dst_width * xmult / 1000;
    ys = dst_height - dst_height * ymult / 1000;
    sizeoffset(dr, zr, xs, ys);

    filterxmult = xmult;
    filterymult = ymult;
    filteroffsetx += (dst_width - aw * 1000 / filterxmult) / 2;
    filteroffsety += (dst_height - ah * 1000 / filterymult) / 2;

end:
    fpux_restore(&fpuv);
}

byte* getfilterbuffer(int* widthp, int* heightp, int* pitch, int* depth)
{
    *widthp = 0;
    *heightp = 0;
    *depth = amiga_depth;
    if (usedfilter == nullptr)
        return nullptr;
    *widthp = gfxvidinfo.width;
    *heightp = gfxvidinfo.height;
    if (pitch)
        *pitch = gfxvidinfo.rowbytes;
    *depth = gfxvidinfo.pixbytes * 8;
    return gfxvidinfo.bufmem;
    #if 0
    RECT dr, sr, zr;
    byte* p;
    int w, h;
    if (usedfilter->type == UAE_FILTER_DIRECT3D)
    {
        return getfilterbuffer3d(widthp, heightp, pitch, depth);
    }
    else
    {
        getfilterrect2(&dr, &sr, &zr, dst_width, dst_height, amiga_width, amiga_height, scale, temp_width, temp_height);
    }
    w = sr.right - sr.left;
    h = sr.bottom - sr.top;
    p = gfxvidinfo.bufmem;
    if (pitch)
        *pitch = gfxvidinfo.rowbytes;
    p += (zr.top - (h / 2)) * gfxvidinfo.rowbytes + (zr.left - (w / 2)) * amiga_depth / 8;
    *widthp = w;
    *heightp = h;
    return p;
    #endif
}

// static void statusline()
// {
//     DDSURFACEDESC2 desc;
//     RECT sr, dr;
//     int y;
//     int lx, ly;
//     int slx, sly;
//
//     if (!(g_curr_conf.leds_on_screen & STATUSLINE_CHIPSET) || !tempsurf)
//         return;
//     statusline_getpos(&slx, &sly, dst_width, dst_height);
//     lx = dst_width;
//     ly = dst_height;
//     SetRect(&sr, slx, 0, slx + lx, TD_TOTAL_HEIGHT);
//     SetRect(&dr, slx, sly, slx + lx, sly + TD_TOTAL_HEIGHT);
//     DirectDraw_BlitRect(tempsurf, &sr, NULL, &dr);
//     if (locksurface(tempsurf, &desc))
//     {
//         for (y = 0; y < TD_TOTAL_HEIGHT; y++)
//         {
//             uae_u8* buf = (uae_u8*)desc.lpSurface + y * desc.lPitch;
//             draw_status_line_single(buf, dst_depth / 8, y, lx, rc, gc, bc, NULL);
//         }
//         unlocksurface(tempsurf);
//         DirectDraw_BlitRect(NULL, &dr, tempsurf, &sr);
//     }
// }

void S2X_configure(int rb, int gb, int bb, int rs, int gs, int bs)
{
    Init_2xSaI(rb, gb, bb, rs, gs, bs);
    hq_init(rb, gb, bb, rs, gs, bs);
    // PAL_init();
    bufmem_ptr = 0;
}

void S2X_reset()
{
    if (!inited)
        return;
    S2X_init(dst_width2, dst_height2, amiga_width2, amiga_height2, dst_depth2, amiga_depth2);
}

void S2X_free()
{
    g_changed_conf.leds_on_screen = g_curr_conf.leds_on_screen = g_curr_conf.leds_on_screen & ~STATUSLINE_TARGET;

    // freesurface(tempsurf);
    // tempsurf = 0;
    // free(tempsurf2);
    // tempsurf2 = 0;
    // free(tempsurf3);
    // tempsurf3 = 0;

    filteroffsetx = 0;
    filteroffsety = 0;
    filterxmult = 1000;
    filterymult = 1000;
    scale = 1;
    inited = false;
}

void S2X_init(int dw, int dh, int aw, int ah, int ad, int dd)
{
    int flags = 0;

    dst_width2 = dw;
    dst_height2 = dh;
    dst_depth2 = dd;
    amiga_width2 = aw;
    amiga_height2 = ah;
    amiga_depth2 = ad;

    S2X_free();
    // d3d = g_curr_conf.gfx_api;
    g_changed_conf.leds_on_screen = g_curr_conf.leds_on_screen = g_curr_conf.leds_on_screen | STATUSLINE_TARGET;

    // if (d3d)
    dd = ad;

    if (dd == 32)
        alloc_colors_rgb(8, 8, 8, 16, 8, 0, 0, 0, 0, 0, rc, gc, bc);
    else
        alloc_colors_rgb(5, 6, 5, 11, 5, 0, 0, 0, 0, 0, rc, gc, bc);

    if (WIN32GFX_IsPicassoScreen())
        return;

    if (!g_curr_conf.gfx_filter || !usedfilter)
    {
        usedfilter = &uaefilters[0];
        scale = 1;
    }
    else
    {
        scale = usedfilter->intmul;
        flags = usedfilter->flags;
        if ((ad == 16 && !(flags & UAE_FILTER_MODE_16)) || (ad == 32 && !(flags & UAE_FILTER_MODE_32)))
        {
            usedfilter = &uaefilters[0];
            scale = 1;
            g_changed_conf.gfx_filter = usedfilter->type;
        }
    }
    // #if 0
    // int res_shift;
    // res_shift = RES_MAX - g_curr_conf.gfx_resolution;
    // if (g_curr_conf.gfx_xcenter_size > 0 && (g_curr_conf.gfx_xcenter_size >> res_shift) < aw)
    //     aw = g_curr_conf.gfx_xcenter_size >> res_shift;
    // res_shift = VRES_MAX - g_curr_conf.gfx_vresolution;
    // if (g_curr_conf.gfx_ycenter_size > 0 && (g_curr_conf.gfx_ycenter_size >> res_shift) < ah)
    //     ah = g_curr_conf.gfx_ycenter_size >> res_shift;
    // #endif
    dst_width = dw;
    dst_height = dh;
    dst_depth = dd;
    amiga_width = aw;
    amiga_height = ah;
    amiga_depth = ad;

    // if (d3d)
    // {
    //     int m = g_curr_conf.gfx_filter_filtermode + 1;
    //     if (m < scale)
    //         m = scale;
    //     temp_width = dst_width * m;
    //     temp_height = dst_height * m;
    // }
    // else
    // {
    //     temp_width = dst_width * 3;
    //     if (temp_width > dxcaps.maxwidth)
    //         temp_width = dxcaps.maxwidth;
    //     temp_height = dst_height * 3;
    //     if (temp_height > dxcaps.maxheight)
    //         temp_height = dxcaps.maxheight;
    //     if (temp_width < dst_width)
    temp_width = dst_width;
    //     if (temp_height < dst_height)
    temp_height = dst_height;
    // }

    // if (usedfilter->type == UAE_FILTER_HQ2X || usedfilter->type == UAE_FILTER_HQ3X || usedfilter->type == UAE_FILTER_HQ4X)
    // {
    //     int w = amiga_width > dst_width ? amiga_width : dst_width;
    //     int h = amiga_height > dst_height ? amiga_height : dst_height;
    //     tempsurf2 = xmalloc(byte, w * h * (amiga_depth / 8) * ((scale + 1) / 2));
    //     tempsurf3 = xmalloc(byte, w * h * (dst_depth / 8) * 4 * scale);
    //     if (!d3d)
    //         tempsurf = allocsystemsurface(temp_width, temp_height);
    // }
    // else
    // {
    //     if (!d3d)
    //         tempsurf = allocsurface(temp_width, temp_height);
    // }
    // if (!tempsurf && !d3d)
    //     Logger::Write(L"DDRAW: failed to create temp surface (%dx%d)\n", temp_width, temp_height);

    inited = true;
}

void S2X_render()
{
    int aw, ah, aws, ahs;
    byte* dptr, * enddptr, * sptr, * endsptr;
    int ok = 0;
    // RECT sr, dr, zr;
    // DDSURFACEDESC2 desc;
    int pitch;
    byte* surfstart;

    aw = amiga_width;
    ah = amiga_height;
    aws = aw * scale;
    ahs = ah * scale;

    if (ah < 16)
        return;
    if (aw < 16)
        return;

    sptr = gfxvidinfo.bufmem;
    endsptr = gfxvidinfo.bufmemend;
    bufmem_ptr = sptr;

    // if (d3d)
    // {
    surfstart = Direct3D::LockTexture(&pitch, true);
    if (surfstart == nullptr)
        return;
    // }
    // else
    // {
    //     if (tempsurf == nullptr)
    //         return;
    //     if (cleartemp)
    //     {
    //         clearsurface(tempsurf);
    //         cleartemp = 0;
    //     }
    //     if (!locksurface(tempsurf, &desc))
    //         return;
    //     pitch = desc.lPitch;
    //     surfstart = (byte*)desc.lpSurface;
    // }
    dptr = surfstart;
    enddptr = dptr + pitch * temp_height;
    // if (!d3d)
    // {
    //     dptr = getfilterrect1(&sr, &dr, dst_width, dst_height, dst_depth, aw, ah, scale, temp_width, temp_height, dptr, pitch);
    // }

    if (!dptr) /* weird things can happen */
        goto end;
    if (dptr < surfstart)
        dptr = surfstart;

    if (usedfilter->type == UAE_FILTER_SCALE2X)   /* 16+32/2X */
    {
        if (amiga_depth == 16 && dst_depth == 16)
        {
            AdMame2x(sptr, gfxvidinfo.rowbytes, dptr, pitch, aw, ah);
            ok = 1;
        }
        else if (amiga_depth == 32 && dst_depth == 32)
        {
            AdMame2x32(sptr, gfxvidinfo.rowbytes, dptr, pitch, aw, ah);
            ok = 1;
        }
    }
    // else if (usedfilter->type == UAE_FILTER_HQ2X || usedfilter->type == UAE_FILTER_HQ3X || usedfilter->type == UAE_FILTER_HQ4X)     /* 32/2X+3X+4X */
    // {
    //     #ifndef CPU_64_BIT
    //
    //     if (tempsurf2 && scale >= 2 && scale <= 4)
    //     {
    //         /* Aaaaaaaarghhhghgh.. */
    //         byte* sptr2 = tempsurf3;
    //         byte* dptr2 = tempsurf2;
    //         int i;
    //         for (i = 0; i < ah; i++)
    //         {
    //             int w = aw * (amiga_depth / 8);
    //             memcpy(dptr2, sptr, w);
    //             dptr2 += w;
    //             sptr += gfxvidinfo.rowbytes;
    //         }
    //         if (amiga_depth == 16 && dst_depth == 32)
    //         {
    //             if (usedfilter->type == UAE_FILTER_HQ2X)
    //                 hq2x_32(tempsurf2, tempsurf3, aw, ah, aws * 4);
    //             else if (usedfilter->type == UAE_FILTER_HQ3X)
    //                 hq3x_32(tempsurf2, tempsurf3, aw, ah, aws * 4);
    //             else if (usedfilter->type == UAE_FILTER_HQ4X)
    //                 hq4x_32(tempsurf2, tempsurf3, aw, ah, aws * 4);
    //             ok = 1;
    //         }
    //         else if (amiga_depth == 16 && dst_depth == 16)
    //         {
    //             if (usedfilter->type == UAE_FILTER_HQ2X)
    //                 hq2x_16(tempsurf2, tempsurf3, aw, ah, aws * 2);
    //             else if (usedfilter->type == UAE_FILTER_HQ3X)
    //                 hq3x_16(tempsurf2, tempsurf3, aw, ah, aws * 2);
    //             else if (usedfilter->type == UAE_FILTER_HQ4X)
    //                 hq4x_16(tempsurf2, tempsurf3, aw, ah, aws * 2);
    //             ok = 1;
    //         }
    //         for (i = 0; i < ah * scale; i++)
    //         {
    //             int w = aw * scale * (dst_depth / 8);
    //             if (dptr + w > enddptr)
    //                 break;
    //             memcpy(dptr, sptr2, w);
    //             sptr2 += w;
    //             dptr += pitch;
    //         }
    //     }
    //     #endif
    //
    // }
    else if (usedfilter->type == UAE_FILTER_SUPEREAGLE)     /* 16/32/2X */
    {
        if (scale == 2 && amiga_depth == 16)
        {
            if (dst_depth == 16)
            {
                SuperEagle_16(sptr, gfxvidinfo.rowbytes, dptr, pitch, aw, ah);
                ok = 1;
            }
            else if (dst_depth == 32)
            {
                SuperEagle_32(sptr, gfxvidinfo.rowbytes, dptr, pitch, aw, ah);
                ok = 1;
            }
        }
    }
    else if (usedfilter->type == UAE_FILTER_SUPER2XSAI)     /* 16/32/2X */
    {
        if (scale == 2 && amiga_depth == 16)
        {
            if (dst_depth == 16)
            {
                Super2xSaI_16(sptr, gfxvidinfo.rowbytes, dptr, pitch, aw, ah);
                ok = 1;
            }
            else if (dst_depth == 32)
            {
                Super2xSaI_32(sptr, gfxvidinfo.rowbytes, dptr, pitch, aw, ah);
                ok = 1;
            }
        }
    }
    else if (usedfilter->type == UAE_FILTER_2XSAI)     /* 16/32/2X */
    {
        if (scale == 2 && amiga_depth == 16)
        {
            if (dst_depth == 16)
            {
                _2xSaI_16(sptr, gfxvidinfo.rowbytes, dptr, pitch, aw, ah);
                ok = 1;
            }
            else if (dst_depth == 32)
            {
                _2xSaI_32(sptr, gfxvidinfo.rowbytes, dptr, pitch, aw, ah);
                ok = 1;
            }
        }
    }
    // else if (usedfilter->type == UAE_FILTER_PAL)     /* 16/32/1X */
    // {
    //     if (amiga_depth == 32 && dst_depth == 32)
    //     {
    //         PAL_1x1_32((uint*)sptr, gfxvidinfo.rowbytes, (uint*)dptr, pitch, aw, ah);
    //         ok = 1;
    //     }
    //     else if (amiga_depth == 16 && dst_depth == 16)
    //     {
    //         PAL_1x1_16((ushort*)sptr, gfxvidinfo.rowbytes, (ushort*)dptr, pitch, aw, ah);
    //         ok = 1;
    //    }
    // }
    else     /* null */
    {
        if (amiga_depth == dst_depth)
        {
            int y;
            for (y = 0; y < ah; y++)
            {
                memcpy(dptr, sptr, aw * dst_depth / 8);
                sptr += gfxvidinfo.rowbytes;
                dptr += pitch;
            }
        }
        ok = 1;
    }

    if (ok == 0 && g_curr_conf.gfx_filter)
    {
        usedfilter = &uaefilters[0];
        g_changed_conf.gfx_filter = usedfilter->type;
    }
end:
    // if (d3d)
    // {
    //     ; //D3D_unlocktexture(); unlock in win32gfx.c
    // }
    // else
    // {
    //     unlocksurface(tempsurf);
    //
    //     getfilterrect2(&dr, &sr, &zr, dst_width, dst_height, aw, ah, scale, temp_width, temp_height);
    //     //Logger::Write(L"(%d %d %d %d) - (%d %d %d %d) (%d %d)\n", dr.left, dr.top, dr.right, dr.bottom, sr.left, sr.top, sr.right, sr.bottom, zr.left, zr.top);
    //     OffsetRect(&sr, zr.left, zr.top);
    //     if (sr.left >= 0 && sr.top >= 0 && sr.right < temp_width && sr.bottom < temp_height)
    //     {
    //         if (sr.left < sr.right && sr.top < sr.bottom)
    //             DirectDraw_BlitRect(nullptr, &dr, tempsurf, &sr);
    //     }
    //     statusline();
    // }

    return;
}

// void S2X_refresh()
// {
//     clearsurface(nullptr);
//     S2X_render();
// }

int S2X_getmult()
{
    if (!usedfilter)
        return 1;
    if (screen_is_picasso)
        return 1;
    return usedfilter->intmul;
}